const { SyncHook } = require('tapable');
const Complation = require("./Complation.js");
const fs = require('fs');
const path = require("path").posix;

/**
 * 代表整个编译对象，负责整个编译的过程，里面会保存所有的编译的信息
 * Compiler类的实例全局唯一
 */
class Compiler {
    constructor(options) {
        this.options = options;
        // 存的是当前 compiler 上面的所有的钩子
        this.hooks = {
            // 开始编译的时候触发
            run: new SyncHook(),
            // 编译结束的时候触发
            done: new SyncHook()
        }
    }
    // 4.执行对象的 run 方法开始执行编译
    run(callback) {
        // 在编译开始之前执行 run 钩子
        this.hooks.run.call();
        const onCompiled = (err, stats, fileDependences) => {
            // 10.在确定好输出内容后，根据配置确定输出的路径和文件名，把文件内容写入到文件系统
            for (let filename in stats.assets) {
                let filePath = path.join(this.options.output.path, filename);
                fs.writeFileSync(filePath, stats.assets[filename], 'utf8');
            }
            callback(null, {
                toJson: () => stats
            })
            // 监听文件变更 并重新编译
            fileDependences.forEach(file => {
                fs.watch(file, () => {
                    this.compile(onCompiled);
                })
            });
        }
        this.compile(onCompiled);
        // 在编译结束之后执行 done 钩子
        this.hooks.done.call();
    }

    compile(onCompiled) {
        // 以后每开启一次新的编译都会创建一个 新的 Complation 实例
        let complation = new Complation(this.options)
        complation.build(onCompiled);
    }
}
module.exports = Compiler;